#pragma once
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
using std::cout;
using std::endl;
class Sock
{
public:
    Sock(std::string type = "TCP")
    {
        if (type == "TCP")
            _type = SOCK_STREAM;
        if (type == "UDP")
            _type = SOCK_DGRAM;

        
    }
    ~Sock()
    {
    }
    // 创建套接字
    void Socket()
    {
        // AF_INET: 网络通信
        // SOCK_DGRAM: 面向数据报 - UDP通信
        _sockfd = socket(AF_INET, _type, 0);
        if (_sockfd < 0)
        {
            cout << "创建套接字失败" << endl;
            printf("%d - %s", errno, strerror(errno));
        }
    }
    // 绑定端口和IP -- 服务器
    // 服务器，虚拟机一般都是ADDR_ANY
    void Bind(uint16_t port)
    {
        // int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = INADDR_ANY;
        int n = bind(_sockfd, (struct sockaddr *)&addr, sizeof(addr));
        if (n < 0)
        {
            cout << "绑定失败" << endl;
            printf("%d - %s", errno, strerror(errno));

        }
    }
    // 进行监听
    void Listen()
    {
        int n = listen(_sockfd, _backlog);
        if (n < 0)
        {
            cout << "监听失败" << endl;
            printf("%d - %s", errno, strerror(errno));
        }
    }
    // 获取连接
    int Accept(std::string* ip, std::uint16_t* port)
    {
        // int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
        struct sockaddr_in addr;
        memset(&addr, sizeof(addr), 0);
        socklen_t addrlen = sizeof(addr);
        int sock = accept(_sockfd, (struct sockaddr*)&addr,&addrlen);
        if(sock < 0)
        {
            cout << "获取连接失败" << endl;
            printf("%d - %s", errno, strerror(errno));
        }
        char buf[32] = {0};
        inet_ntop(AF_INET,&addr.sin_addr.s_addr,buf, sizeof(buf));
        *ip = buf;
        *port = ntohs(addr.sin_port);
        cout << "ip = " << *ip  << "port = " << *port << endl;
        return sock;
    }
    // 建立连接
    void Connect(const std::string& ip, const uint16_t& port)
    {
        // int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);
        int n = connect(_sockfd,(struct sockaddr*)&addr,sizeof(addr));
        if(n < 0)
        {
            cout << "获取连接失败" << endl;
            printf("%d - %s", errno, strerror(errno));
        }
    }

    int Fd()
    {
        return _sockfd;
    }

private:
    int _sockfd;
    int _type;
    int _backlog = 10;
};